#include <iostream>
#include"comm.hpp"
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>

const int size = 4096;
const int keynum = 0x666;

#define CREATE "create"
#define USER "user"


#define PATH "."

class Shm
{
public:
    Shm(const std::string path, int keynum,std::string role)
        : _shmsize(size), _shmstr(nullptr),_role(role)
    {
        _key = ftok(path.c_str(), keynum);
        if (_key < 0)
        {
            ERR_EXIT("ftok error!");
        }
        printf("ftok success!\n");
        if(_role==CREATE)
        {
            Create();
        }
        else{
            Get();
        }

        Attach();
    }

    

    void *GetStr()
    {
        return _shmstr;
    }

    ~Shm()
    {
        Cancel_Attach();
        if(_role==CREATE)
        {
            Distory();
            printf("server end normer!\n");
        }
        
    }

    void Attr()
    {
        struct shmid_ds ds;
        int n=shmctl(_shmid,IPC_STAT,&ds);
        printf("shm_segse:%ld\n",ds.shm_segsz);
        printf("key:0x%x\n",ds.shm_perm.__key);
    }

private:
    void CreateHelper(int shm)
    {
        _shmid = shmget(_key, size, shm);
        if (_shmid < 0)
        {
            ERR_EXIT("shm error");
        }
        printf("shm create success!\n");
    }

    void Create()
    {
        CreateHelper(IPC_CREAT | IPC_EXCL | 0666);
    }

    void Get()
    {
        CreateHelper(IPC_CREAT);
    }

    void Attach()
    {
        _shmstr = shmat(_shmid, nullptr, 0);
        if ((long long)_shmstr < 0)
        {
            ERR_EXIT("shmat");
        }
        printf("shmat success!\n");
    }

    void Cancel_Attach()
    {
        int ret=shmdt(_shmstr);
        if(ret<0)
        {
            ERR_EXIT("cancel attach");
        }
        printf("cancel attach success!\n");
    }

    void Distory()
    {
        int shmd = shmctl(_shmid, IPC_RMID, nullptr);
        if (shmd < 0)
        {
            ERR_EXIT("shmctl");
        }
        printf("shm destory success!\n");
    }

    key_t _key;
    int _shmid;
    size_t _shmsize;
    void *_shmstr;
    std::string _role;
};
